#!/usr/bin/env bash
# vim:ts=4:sw=4:expandtab

###########################################################################
# NAME
#     mp-exec - tool for exec maopao task
#
# SYNOPSIS
#     mp-exec [ options ]
#
#     debug=on mp-exec ...
#
# OPTIONS
#       -f TASKFILE Set taskfile to exec (default is STDIN).
#       -h          Print this message and exit.
#
# AUTHORS
#     neiku project <ku7d@qq.com>
#
# VERSION
#     2017/01/15: 支持以PULL模式执行任务-拉取文件
#     2017/01/16: 支持拉取文件后，继续转发任务（二分法）
#                 统一使用maopao用户名+RSA密钥方式自动验证，SSH端口默认22
#                 统一使用-o方式传递参数到ssh，-b方式执行脚本（兼容性最好）
#                 - sftp -b 选项在MAC测试必须要用密钥验证
#                 - sftp -i/-P 选项在LINUX上不支持，必须用-o选项实现
#
###########################################################################

# help
function help()
{
    echo "Usage: mp-exec [ options ]"
    echo "Options:"
    echo "    -f TASKFILE Set taskfile to exec (default is STDIN)."
    echo "    -h          Print this message and exit."
    echo ""
    echo "Report bugs to YIF <ku7d@qq.com>"
}

cmdline_taskfile=""

# parse cmdline
mp-log debug "origin-args:[$@]"
temp=$(getopt -o "u:H:P:f:h" --long "" -n "mp-exec" -- "$@")
if [ $? != 0 ] ; then
    echo "`help`" >&2
    exit 1
fi
eval set -- "$temp"
mp-log debug "parsed-args:[$temp]"
while true
do
    case "$1" in
        -f) cmdline_taskfile="$2" ;  shift 2 ;;
        -h) echo "`help`" >&2; exit 0;;
        --) shift ; break ;;
        *)  echo "parse options error!" >&2 ; exit 1 ;;
    esac
done
mp-log debug "taskfile:[$cmdline_taskfile]"

# load task content
task=""
if [ ! -z "$cmdline_taskfile" ] ; then
    task="`cat "$cmdline_taskfile"`"
else
    echo "please give me the task (end with ctrl+d):"
    task="`cat -`"
    echo "ok! i got the task, there are `echo "$task" | wc -l` lines."
    echo ""
fi
mp-log debug "task:[\n$task\n]"

# parse task
taskseq=""
srchost=""
dsthost=""
othhost=""
srcroot=""
dstroot=""
file_task_metainfo=""
file_task_filelist=""

## task's metainfo
metainfo="$(echo "$task" | while read line; do if [ -z "$line" ] ; then break; fi; echo "$line"; done)"
taskseq="$(echo "$metainfo" | grep -i -w "^[ \t]*TaskSeq[ \t]*:" | tr -d ' ' | tail -n 1| awk -F':' '{print $2}')"
srchost="$(echo "$metainfo" | grep -i -w "^[ \t]*SrcHost[ \t]*:" | tr -d ' ' | tail -n 1| awk -F':' '{print $2}')"
dsthost="$(echo "$metainfo" | grep -i -w "^[ \t]*DstHost[ \t]*:" | tr -d ' ' | tail -n 1| awk -F':' '{print $2}')"
othhost="$(echo "$metainfo" | grep -i -w "^[ \t]*OthHost[ \t]*:" | tr -d ' ' | tail -n 1| awk -F':' '{print $2}')"
srcroot="$(echo "$metainfo" | grep -i -w "^[ \t]*SrcRoot[ \t]*:" | tr -d ' ' | tail -n 1| awk -F':' '{print $2}')"
dstroot="$(echo "$metainfo" | grep -i -w "^[ \t]*DstRoot[ \t]*:" | tr -d ' ' | tail -n 1| awk -F':' '{print $2}')"
mp-log debug "metainfo:[\n$metainfo\n], taskseq:[$taskseq]," \
             "srchost:[$srchost], dsthost:[$dsthost], othhost:[$othhost]," \
             "srcroot:[$srcroot], dstroot:[$dstroot]"

## save metainfo & filelist
file_task_metainfo="./task_metainfo_$taskseq.txt"
file_task_filelist="./task_filelist_$taskseq.txt"
echo "$metainfo" > $file_task_metainfo
echo "$task" | tac | while read line; do if [ -z "$line" ] ; then break; fi; echo "$line"; done | tac > $file_task_filelist
filecount="$(wc -l $file_task_filelist | awk '{print $1}')"
mp-log debug "metainfo-file:[$file_task_metainfo], filelist-file:[$file_task_filelist], filelist-count:[$filecount]"

# pull files
if [ ! -z "$srchost" -a "$filecount" -ne "0" ] ; then
    ## scripts
    file_task_mkdir="./task_mkdir_$taskseq.sh"
    file_task_pull="./task_pull_$taskseq.sftp"
    mp-log debug "mkdir-script:[$file_task_mkdir], pull-script:[$file_task_pull]"

    ## generate mkdir commands (sh)
    > $file_task_mkdir
    cat $file_task_filelist \
        | while read filename; do echo "`dirname $filename`"; done | sort -u \
        | while read dirname; do echo "mkdir -pv '$dstroot/$dirname' || exit 1" >> $file_task_mkdir; done
    echo "echo mkdir end" >> $file_task_mkdir

    ## execute mkdir commands (sh)
    sh $file_task_mkdir
    if [ $? -ne 0 ] ; then
        mp-log error "mkdir fail, taskseq:[$taskseq], mkdir-script:[$file_task_mkdir]"
        exit 1
    fi

    ## generate pull commands (sftp)
    > $file_task_pull
    cat $file_task_filelist \
        | while read filename; do echo "get '$srcroot/$filename' '$dstroot/$filename'" >> $file_task_pull; done
    echo "quit" >> $file_task_pull

    ## execute pull commands (sftp)
    sftp -b $file_task_pull -oIdentityFile=~/.ssh/id_rsa.maopao -oPort=22 maopao@$srchost
    if [ $? -ne 0 ] ; then
        mp-log error "pull fail, taskseq:[$taskseq], pull-script:[$file_task_pull]"
        exit 1
    fi
fi

# forward tasks
if [ ! -z "$othhost" -a "$filecount" -ne "0" ] ; then
    subdsthost1=""
    subothhost1=""
    subdsthost2=""
    subothhost2=""
    file_task_subtask1="./task_subtask1_$taskseq.mp"
    file_task_subtask2="./task_subtask2_$taskseq.mp"

    iplist="$othhost"
    iplist="$(echo "$iplist" | tr ',' '\n' | sort -R | sort -R | tr '\n' ',' | sed 's/,$//g')"
    count="$(echo "$iplist" | tr ',' '\n'  | wc -l)"
    iplist1="$(echo "$iplist" | tr ',' '\n' | head -n -$((count/2)) | tr '\n' ',' | sed 's/,$//g')"
    iplist2="$(echo "$iplist" | tr ',' '\n' | tail -n -$((count/2)) | tr '\n' ',' | sed 's/,$//g')"
    subdsthost1="$(echo "$iplist1" | tr ',' '\n' | head -n +1)"
    subothhost1="$(echo "$iplist1" | tr ',' '\n' | tail -n +2 | tr '\n' ',' | sed 's/,$//g')"
    subdsthost2="$(echo "$iplist2" | tr ',' '\n' | head -n +1)"
    subothhost2="$(echo "$iplist2" | tr ',' '\n' | tail -n +2 | tr '\n' ',' | sed 's/,$//g')"
    mp-log debug "subdsthost1:[$subdsthost1], subothhost1:[$subothhost1]," \
                 "subdsthost2:[$subdsthost2], subothhost2:[$subothhost2]," \
                 "subtask1-file:[$file_task_subtask1], subtask1-file:[$file_task_subtask2]" \
                 "iplist:[$iplist], iplist1:[$iplist1], iplist2:[$iplist2]"

    ## forward sub-task1
    if [ ! -z "$subdsthost1" ] ; then
        mp-create -t "$taskseq" -s "$dsthost" -d "$subdsthost1" -o "$subothhost1" \
                  -q "$dstroot" -p "$dstroot" \
                  -f "$file_task_filelist" -O "$file_task_subtask1"
        if [ $? -ne 0 ] ; then
            mp-log error "create sub-task1 fail, taskseq:[$taskseq], subdsthost1:[$subdsthost1]"
            exit 1
        fi

        mp-send -u maopao -H "$subdsthost1" -P "22" -f "$file_task_subtask1"
        if [ $? -ne 0 ] ; then
            mp-log error "send sub-task1 fail, taskseq:[$taskseq], subdsthost1:[$subdsthost1]"
            exit 1
        fi
    fi

    ## forward sub-task2
    if [ ! -z "$subdsthost2" ] ;  then
        mp-create -t "$taskseq" -s "$dsthost" -d "$subdsthost2" -o "$subothhost2" \
                  -q "$dstroot" -p "$dstroot" \
                  -f "$file_task_filelist" -O "$file_task_subtask2"
        if [ $? -ne 0 ] ; then
            mp-log error "create sub-task2 fail, taskseq:[$taskseq], subdsthost2:[$subdsthost2]"
            exit 1
        fi

        mp-send -u maopao -H "$subdsthost2" -P "22" -f "$file_task_subtask2"
        if [ $? -ne 0 ] ; then
            mp-log error "send sub-task2 fail, taskseq:[$taskseq], subdsthost2:[$subdsthost2]"
            exit 1
        fi
    fi
fi
